local extension = Package("rfenghou_hall_of_fame")
extension.extensionName = "aaa_fenghou"

local U = require "packages/utility/utility"
local RUtil = require "packages/aaa_fenghou/utility/rfenghou_util"

Fk:loadTranslationTable{
  ["rfenghou_hall_of_fame"] = "荣誉室！",
  ["rfamehall"] = "封侯荣誉", -- 幽默谐音
}

local dante = General:new(extension, "rfenghou__dante", "west", 3)
dante.hidden = true
local huanghuang = fk.CreateTriggerSkill{
  name = "rfenghou__huanghuang",
  anim_type = "special",
  frequency = Skill.Compulsory,
  events = {fk.RoundStart, fk.EventPhaseStart, fk.AfterDying},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      if event == fk.RoundStart then
        return true
      elseif event == fk.EventPhaseStart then
        return target == player and player.phase == Player.Play
      elseif event == fk.AfterDying then
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    for _, p in ipairs(room.alive_players) do
      if (event == fk.RoundStart and player:getMark("@rfenghou__huanghuang1") == 1) or
        (event == fk.EventPhaseStart and player:getMark("@rfenghou__huanghuang2") == 1) or
        (event == fk.AfterDying and player:getMark("@rfenghou__huanghuang3") == 1) then
        if p:hasSkill("rfenghou__qiqi") and not p.faceup then
          p:drawCards(3, self.name)
        else
          local x = math.min(p:getHandcardNum(), 3)
          room:askForDiscard(p, x, x, false, self.name, false)
        end
        room:setPlayerMark(player, "rfenghou__huanghuangthrow", 1)
      end
      if (event == fk.RoundStart and player:getMark("@rfenghou__huanghuang1") == 2) or
        (event == fk.EventPhaseStart and player:getMark("@rfenghou__huanghuang2") == 2) or
        (event == fk.AfterDying and player:getMark("@rfenghou__huanghuang3") == 2) then
        if p:hasSkill("rfenghou__qiqi") and not p.faceup then
          if p:isWounded() then
            room:recover({
              who = p,
              num = 1,
              recoverBy = p,
              skillName = self.name
            })
          end
        else
          room:loseHp(p, 1, self.name)
        end
        room:setPlayerMark(player, "rfenghou__huanghuanglosehp", 1)
      end
    if (event == fk.RoundStart and player:getMark("@rfenghou__huanghuang1") == 3) or
      (event == fk.EventPhaseStart and player:getMark("@rfenghou__huanghuang2") == 3) or
      (event == fk.AfterDying and player:getMark("@rfenghou__huanghuang3") == 3) then
      p:drawCards(3)
      room:setPlayerMark(player, "rfenghou__huanghuangdraw", 1)
    end
  end
    if player:getMark("rfenghou__huanghuangthrow") == 1 and player:getMark("rfenghou__huanghuanglosehp") == 1 and player:getMark("rfenghou__huanghuangdraw") == 1 then
      room:setPlayerMark(player, "rfenghou__huanghuangthrow", 0)
      room:setPlayerMark(player, "rfenghou__huanghuanglosehp", 0)
      room:setPlayerMark(player, "rfenghou__huanghuangdraw", 0)
      local now = {player:getMark("@rfenghou__huanghuang1"),player:getMark("@rfenghou__huanghuang2"),player:getMark("@rfenghou__huanghuang3")}
      local lists = {{1,2,3},{1,3,2},{2,1,3},{2,3,1},{3,1,2},{3,2,1}}
      table.removeOne(lists, now)
      local to = table.random(lists)
      room:setPlayerMark(player, "@rfenghou__huanghuang1", to[1])
      room:setPlayerMark(player, "@rfenghou__huanghuang2", to[2])
      room:setPlayerMark(player, "@rfenghou__huanghuang3", to[3])
    end
  end,


  refresh_events = {fk.GameStart},
  can_refresh = function(self, event, target, player, data)
    return player:hasSkill(self)
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    room:setPlayerMark(player, "@rfenghou__huanghuang1", 1)
    room:setPlayerMark(player, "@rfenghou__huanghuang2", 2)
    room:setPlayerMark(player, "@rfenghou__huanghuang3", 3)
  end
}
local qiqi = fk.CreateTriggerSkill{
  name = "rfenghou__qiqi",
  anim_type = "negative",
  frequency = Skill.Compulsory,
  events = {fk.Damaged},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and data.from
  end,
  on_use = function(self, event, target, player, data)
    player:turnOver()
    if not data.from.dead then
      data.from:turnOver()
    end
  end
}
dante:addSkill(huanghuang)
dante:addSkill(qiqi)
Fk:loadTranslationTable{
  ["rfenghou__dante"] = "但丁",
  ["#rfenghou__dante"] = "终结与开端",
  ["illustrator:rfenghou__dante"] = "昆特牌",
  ["designer:rfenghou__dante"] = "涓人",

  ["@rfenghou__huanghuang1"] = "每轮时机",
  ["@rfenghou__huanghuang2"] = "出牌时机",
  ["@rfenghou__huanghuang3"] = "濒死时机",
  ["rfenghou__huanghuang"] = "惶惶喜剧",
  [":rfenghou__huanghuang"] = "锁定技，（每轮开始），所有角色各弃三张牌；（出牌阶段开始时），所有角色各失去1点体力；（一名角色脱离濒死状态后），"..
  "所有角色各摸三张牌。均执行后，随机调换（）中的内容。",
  ["rfenghou__qiqi"] = "泣泣于异",
  [":rfenghou__qiqi"] = "锁定技，你受到伤害后，你和伤害来源翻面；若你武将牌背面朝上，〖惶惶喜剧〗对你的负面效果反转。",
}

local shiva = General:new(extension, "rfenghou__shiva", "west", 6)
shiva.hidden = true
local jinyong = fk.CreateTriggerSkill{
  name = "rfenghou__jinyong",
  anim_type = "offensive",
  events = {fk.Damage},
  frequency = Skill.Compulsory,
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and target and target ~= data.to and not data.to.dead and not target.dead
    and (target == player or data.to == player)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local to = (target == player) and data.to or target
    for _, p in ipairs({to, player}) do
      if not p.dead then
        room:loseHp(p, 1, self.name)
      end
    end
    for _, p in ipairs({to, player}) do
      if not p.dead then
        room:recover { num = 1, skillName = self.name, who = p, recoverBy = player }
      end
    end
  end,
}
shiva:addSkill(jinyong)


local wanxiang = fk.CreateViewAsSkill{
  name = "rfenghou__wanxiang",
  anim_type = "offensive",
  pattern = ".",
  prompt = "#rfenghou__wanxiang",
  interaction = function(self)
    local all_names = Self:getMark("rfenghou__wanxiang_names")
    local names = U.getViewAsCardNames(Self, self.name, all_names)
    if #names > 0 then
      return U.CardNameBox { choices = names }
    end
  end,
  card_filter = function(self, to_select, selected)
    return #selected == 0
  end,
  view_as = function(self, cards)
    if #cards ~= 1 or not self.interaction.data then return nil end
    local c = Fk:cloneCard(self.interaction.data)
    c.skillName = self.name
    c:addSubcard(cards[1])
    return c
  end,
  enabled_at_play = function(self, player)
    return true
  end,
  enabled_at_response = function (self, player, response)
    return true
  end,
}

local wanxiang_prohibit = fk.CreateProhibitSkill{
  name = "#rfenghou__wanxiang_prohibit",
  prohibit_use = function(self, player, card)
    if not player:hasSkill(wanxiang) then return false end
    local cards = Card:getIdList(card)
    if #cards > 0 and table.find(cards, function(id)
      return card.trueName == Fk:getCardById(id, true).trueName
    end) then return true end
    local mark = player:getMark("@rfenghou__wanxiang-turn")
    if mark ~= 0 then
      -- 禁止0点牌会导致无法通过任何合法性监测……
      if card.number > 0 and card.number <= mark[1] then return true end
      local nameLen = U.ConvertNumber(mark[2], true)
      return Fk:translate(card.trueName, "zh_CN"):len() <= nameLen
    end
  end,
  prohibit_response = function(self, player, card)
    if not player:hasSkill(wanxiang) then return false end
    local cards = Card:getIdList(card)
    return #cards > 0 and table.find(cards, function(id)
      return card.trueName == Fk:getCardById(id, true).trueName
    end)
  end,
}
wanxiang:addRelatedSkill(wanxiang_prohibit)

local wanxiang_targetmod = fk.CreateTargetModSkill{
  name = "#rfenghou__wanxiang_targetmod",
  bypass_distances = function(self, player, skill, card)
    return table.contains(card.skillNames, wanxiang.name)
  end,
}
wanxiang:addRelatedSkill(wanxiang_targetmod)

local wanxiang_trigger = fk.CreateTriggerSkill{
  name = "#rfenghou__wanxiang_trigger",
  events = {fk.TurnEnd},
  anim_type = "control",
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(wanxiang) then
      local tos, check = {}, false
      local useEvents = player.room.logic:getEventsOfScope(GameEvent.UseCard, 1, function(e)
        local use = e.data[1]
        table.insertIfNeed(tos, use.from)
        check = check or use.from == player.id
        for _, pid in ipairs(TargetGroup:getRealTargets(use.tos)) do
          table.insertIfNeed(tos, pid)
        end
        return false
      end, Player.HistoryTurn)
      if check then
        player.room:sortPlayersByAction(tos)
        self.cost_data = {tos = tos}
        return true
      end
    end
  end,
  on_cost = Util.TrueFunc,
  on_use = function (self, event, target, player, data)
    local room = player.room
    for _, pid in ipairs(self.cost_data.tos) do
      local p = room:getPlayerById(pid)
      local cards = p:getCardIds("hej")
      room:recastCard(cards, p, wanxiang.name)
    end
  end,

  refresh_events = {fk.EventAcquireSkill, fk.CardUsing},
  can_refresh = function (self, event, target, player, data)
    if event == fk.EventAcquireSkill then
      return target == player and data == wanxiang
    else
      return target == player and player:hasSkill(wanxiang, true)
    end
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if event == fk.EventAcquireSkill then
      -- FIXEME: 需要排序后的牌名表 all_card_names
      if player:getMark("rfenghou__wanxiang_names") == 0 then
        local names = {{}, {}, {}}
        for _, card in ipairs(Fk.cards) do
          if not table.contains(Fk:currentRoom().disabled_packs, card.package.name) and not card.is_derived then
            table.insertIfNeed(names[card.type], card.name)
          end
        end
        names = table.connect(names[1], names[2], names[3])
        room:setPlayerMark(player, "rfenghou__wanxiang_names", names)
      end
      local turnEvent = room.logic:getCurrentEvent():findParent(GameEvent.Turn)
      if turnEvent then
        local useEvents = room.logic:getEventsByRule(GameEvent.UseCard, 1, function (e)
          return e.data[1].from == player.id
        end, turnEvent.id)
        if #useEvents > 0 then
          local useCard = useEvents[1].data[1].card
          room:setPlayerMark(player, "@rfenghou__wanxiang-turn", {useCard.number, U.ConvertNumber(Fk:translate(useCard.trueName, "zh_CN"):len())})
        end
      end
    else
      local nameLen = U.ConvertNumber(Fk:translate(data.card.trueName, "zh_CN"):len())
      room:setPlayerMark(player, "@rfenghou__wanxiang-turn", {data.card.number, nameLen})
    end
  end,
}
wanxiang:addRelatedSkill(wanxiang_trigger)

-- 转化装备改为打印装备真牌，进入弃牌堆时销毁
local wanxiang_fakeequip = fk.CreateTriggerSkill{
  name = "#rfenghou__wanxiang_fakeequip",
  events = {fk.PreCardUse},
  mute = true,
  can_trigger = function(self, event, target, player, data)
    return target == player and data.card.type == Card.TypeEquip and #data.card.subcards == 1
  end,
  on_cost = Util.TrueFunc,
  on_use = function (self, event, target, player, data)
    local room = player.room
    local info = {data.card.name, data.card.suit, data.card.number}
    room:moveCardTo(data.card.subcards, Card.Void, nil, fk.ReasonJustMove, self.name, nil, true)
    local equip = room:printCard(info[1], info[2], info[3])
    room:setCardMark(equip, "__vitural_equip", data.card.subcards[1])
    room:useCard{from = player.id, tos = data.tos, card = equip}
    return true
  end,
  
  refresh_events = {fk.AfterCardsMove},
  can_refresh = function (self, event, target, player, data)
    return player == player.room.players[1]
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    for _, move in ipairs(data) do
      if move.toArea == Card.DiscardPile then
        for _, info in ipairs(move.moveInfo) do
          local cid = info.cardId
          local orgi = Fk:getCardById(cid):getMark("__vitural_equip")
          if orgi ~= 0 and room:getCardArea(cid) == Card.DiscardPile then
            table.removeOne(room.void, orgi)
            table.insert(room.discard_pile, orgi)
            room:setCardArea(orgi, Card.DiscardPile)
            table.removeOne(room.discard_pile, cid)
            table.insert(room.void, cid)
            room:setCardArea(cid, Card.Void)
            room:setCardMark(Fk:getCardById(cid), "__vitural_equip", 0)
          end
        end
      end
    end
  end,
}
wanxiang:addRelatedSkill(wanxiang_fakeequip)
shiva:addSkill(wanxiang)
Fk:loadTranslationTable{
  ["rfenghou__shiva"] = "湿婆",
  ["#rfenghou__shiva"] = "毁世方生",
  ["designer:rfenghou__shiva"] = "扬林",
  ["illustrator:rfenghou__shiva"] = "",

  ["rfenghou__jinyong"] = "烬涌",
  [":rfenghou__jinyong"] = "锁定技，一名角色对另一名角色造成伤害后，若你为其中之一，对方与你依次失去1点体力，再依次回复1点体力。",
  ["rfenghou__wanxiang"] = "万相",
  [":rfenghou__wanxiang"] = "锁定技，你仅能将你的牌当与此牌不同名的牌且无距离限制地使用或打出。同一回合内，你使用牌的点数和牌名字数须大于你使用的"..
  "上一张牌。你使用过牌的回合结束时，当前回合使用或被使用过牌的角色须重铸其区域内的所有牌。",
  ["#rfenghou__wanxiang"] = "万相：将一张牌转化为牌名不同的任意牌",
  ["#rfenghou__wanxiang_trigger"] = "万相",
  ["@rfenghou__wanxiang-turn"] = "万相",
  ["#rfenghou__wanxiang_fakeequip"] = "万相",
}

local shakespeare = General:new(extension, "rfenghou__shakespeare", "west", 3)
shakespeare.hidden = true
local lianpian = fk.CreateTriggerSkill{
  name = "rfenghou__lianpian",
  anim_type = "control",
  frequency = Skill.Compulsory,
  events = {fk.TargetSpecified},
  can_trigger = function(self, event, target, player, data)
    return target == player and player:hasSkill(self) and data.card.type == Card.TypeTrick and data.firstTarget and
      table.find(AimGroup:getAllTargets(data.tos), function(id)
        return id ~= player.id and not player.room:getPlayerById(id).dead
      end)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    for _, id in ipairs(AimGroup:getAllTargets(data.tos)) do
      if id ~= player.id then
        local p = room:getPlayerById(id)
        if p.dead then
          --continue
        elseif p:getMark("__hidden_general") == 0 and p:getMark("__hidden_deputy") == 0 then
          RUtil.EnterHidden(p)
        elseif not p.chained then
          p:setChainState(true)
        else
          p:turnOver()
          if not p.dead and p.chained then
            p:setChainState(false)
          end
          if not p.dead then
            local skill = Fk.skills["hidden_skill&"]
            if p:getMark("__hidden_general") ~= 0 or p:getMark("__hidden_deputy") ~= 0 then
              skill:trigger(fk.TurnStart, p, p, data)
            end
          end
        end
      end
    end
  end,
}
local zongxi = fk.CreateTriggerSkill{
  name = "rfenghou__zongxi",
  anim_type = "control",
  events = {fk.SkillEffect, "fk.GeneralAppeared"},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      if event == fk.SkillEffect then
        if data.name == "hidden_skill&" and not target.dead and
          (target:getMark("__hidden_general") ~= 0 or target:getMark("__hidden_deputy") ~= 0) then
          local room = player.room
          local info = room.tag["rfenghou__zongxi"] or {}
          if #info == 0 then return end
          local record = info[#info].event
          local changeHp_event = room.logic:getCurrentEvent():findParent(GameEvent.ChangeHp)
          if changeHp_event and changeHp_event.data[1] == target then
            if record ~= fk.HpChanged then return end
          end
          local skill_event = room.logic:getCurrentEvent():findParent(GameEvent.SkillEffect, false)
          if skill_event and skill_event.data[3].name == "rfenghou__lianpian" then
            if record ~= fk.SkillEffect then return end
          end
          local turn_event = room.logic:getCurrentEvent():findParent(GameEvent.Turn)
          if turn_event and turn_event.data[1] == target then
            if record ~= fk.TurnStart then return end
          end
          return true
        end
      elseif event == "fk.GeneralAppeared" and not target.dead then
        local info = player.room.tag["rfenghou__zongxi"] or {}
        if #info == 0 then return end
        for i = #info, 1, -1 do
          if info[i].to == target.id then
            if i == 1 then return end
            local p = player.room:getPlayerById(info[i - 1].to)
            if not p.dead then
              self.cost_data = p.id
              return true
            end
          end
        end
      end
    end
  end,
  on_cost = function (self, event, target, player, data)
    if event == fk.SkillEffect then
      return true
    elseif event == "fk.GeneralAppeared" then
      local room = player.room
      room:setPlayerMark(player, "rfenghou__zongxi-tmp", {target.id, self.cost_data})
      local success, dat = room:askForUseActiveSkill(player, "rfenghou__zongxi_active",
        "#rfenghou__zongxi-choose:"..target.id..":"..self.cost_data, true)
      room:setPlayerMark(player, "rfenghou__zongxi-tmp", 0)
      if success then
        self.cost_data = {dat, self.cost_data}
        return true
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    if event == fk.SkillEffect then
      local e = player.room.logic:getCurrentEvent():findParent(GameEvent.SkillEffect)
      e:shutdown()
    elseif event == "fk.GeneralAppeared" then
      local card = Fk:cloneCard(self.cost_data[1].interaction)
      card.skillName = self.name
      local tos = {}
      if #self.cost_data[1].targets > 0 then
        tos = {{self.cost_data[2]}, self.cost_data[1].targets}
      else
        tos = {{self.cost_data[2]}}
      end
      local use = {
        from = target.id,
        tos = tos,
        card = card,
        extraUse = true,
      }
      room:useCard(use)
    end
  end,

  refresh_events = {"fk.GeneralAppeared", fk.PreDamage},
  can_refresh = function (self, event, target, player, data)
    if event == "fk.GeneralAppeared" then
      return target == player
    elseif event == fk.PreDamage then
      return data.card and table.contains(data.card.skillNames, self.name) and data.damageType ~= fk.ThunderDamage
    end
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if event == "fk.GeneralAppeared" then  --隐匿原因记录器
      local event_data = {to = target.id}
      local changeHp_event = room.logic:getCurrentEvent():findParent(GameEvent.ChangeHp, true)
      if changeHp_event and changeHp_event.data[1] == target then
        event_data["event"] = fk.HpChanged
      end
      local skill_event = room.logic:getCurrentEvent():findParent(GameEvent.SkillEffect, false)
      if event_data["event"] == nil and skill_event and
        table.contains({"rfenghou__lianpian", "rfenghou__xiuchou", "rfenghou__fuzhi", "rfenghou_hongdang__lianpian"},  --耦！
          skill_event.data[3].name) then
        event_data["event"] = fk.SkillEffect
      end
      local turn_event = room.logic:getCurrentEvent():findParent(GameEvent.Turn, true)
      if event_data["event"] == nil and turn_event and turn_event.data[1] == target then
        event_data["event"] = fk.TurnStart
      end
      local tag = room.tag["rfenghou__zongxi"] or {}
      table.insert(tag, event_data)
      room.tag["rfenghou__zongxi"] = tag
    elseif event == fk.PreDamage then
      data.damageType = fk.ThunderDamage
    end
  end,
}
local zongxi_active = fk.CreateActiveSkill{
  name = "rfenghou__zongxi_active",
  card_num = 0,
  min_target_num = 0,
  interaction = function()
    local all_names = U.getAllCardNames("t")
    local names = {}
    local player = Fk:currentRoom():getPlayerById(Self:getMark("rfenghou__zongxi-tmp")[1])
    local target = Fk:currentRoom():getPlayerById(Self:getMark("rfenghou__zongxi-tmp")[2])
    for _, name in ipairs(all_names) do
      local card = Fk:cloneCard(name)
      card.skillName = "rfenghou__zongxi"
      if not player:prohibitUse(card) and player:canUseTo(card, target, {bypass_distances = true, bypass_times = true}) then
        table.insert(names, name)
      end
    end
    return U.CardNameBox { choices = names, all_choices = all_names }
  end,
  card_filter = Util.FalseFunc,
  target_filter = function(self, to_select, selected)
    local card = Fk:cloneCard(self.interaction.data)
    card.skillName = "rfenghou__zongxi"
    local player = Fk:currentRoom():getPlayerById(Self:getMark("rfenghou__zongxi-tmp")[1])
    if card.skill:getMinTargetNum() < 2 then return false end
    return not player:isProhibited(Fk:currentRoom():getPlayerById(to_select), card) and
      card.skill:modTargetFilter(to_select, {Self:getMark("rfenghou__zongxi-tmp")[2]},
      player, card, true)
  end,
  feasible = function(self, selected, selected_cards)
    local card = Fk:cloneCard(self.interaction.data)
    card.skillName = "rfenghou__zongxi"
    local player = Fk:currentRoom():getPlayerById(Self:getMark("rfenghou__zongxi-tmp")[1])
    return #selected >= card.skill:getMinTargetNum() - 1 and #selected <= card.skill:getMaxTargetNum(player, card) - 1
  end,
}
Fk:addSkill(zongxi_active)
shakespeare:addSkill(lianpian)
shakespeare:addSkill(zongxi)
Fk:loadTranslationTable{
  ["rfenghou__shakespeare"] = "莎士比亚",
  ["#rfenghou__shakespeare"] = "",
  ["designer:rfenghou__shakespeare"] = "白驹",
  ["illustrator:rfenghou__shakespeare"] = "John Taylor",

  ["rfenghou__lianpian"] = "连篇",
  [":rfenghou__lianpian"] = "锁定技，当你使用锦囊牌指定其他角色为目标后，其隐匿；若其已隐匿，改为其横置；若其已横置，改为其依次翻面、重置、登场。",
  ["rfenghou__zongxi"] = "纵戏",
  [":rfenghou__zongxi"] = "当隐匿角色登场前，若其此次<a href='rfenghou__zongxi_unhidden'>登场方式</a>与上一名登场角色的登场方式相同，"..
  "则防止之；当隐匿角色登场后，你可以声明一张普通锦囊牌牌名，视为其对上一名登场角色使用之，此牌造成的伤害改为雷电伤害。",
  ["rfenghou__zongxi_unhidden"] = "因扣减体力登场、回合开始时登场、因技能登场。",
  ["rfenghou__zongxi_active"] = "纵戏",
  ["#rfenghou__zongxi-choose"] = "纵戏：选择视为 %src 对 %dest 使用的牌（若为【借刀杀人】，再选择副目标）",
}

local tuobagui = General:new(extension, "rfenghou__tuobagui", "wei", 4)
tuobagui.hidden = true
local yundao = fk.CreateTriggerSkill{
  name = "rfenghou__yundao",
  anim_type = "control",
  events = {fk.RoundStart},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self)
  end,
  on_cost = function (self, event, target, player, data)
    local target1 = player:getLastAlive(true, player:getMark("rfenghou__yundao1") + 1)
    local target2 = player:getNextAlive(true, player:getMark("rfenghou__yundao2") + 1)
    return player.room:askForSkillInvoke(player, self.name, nil, "#rfenghou__yundao-invoke:"..target1.id..":"..target2.id)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local target1 = player:getLastAlive(true, player:getMark("rfenghou__yundao1") + 1)
    local target2 = player:getNextAlive(true, player:getMark("rfenghou__yundao2") + 1)
    room:doIndicate(player.id, {target1.id, target2.id})
    room:swapSeat(target1, target2)
    if room.current.seat ~= 1 then
      room.current = room.players[#room.players]:getNextAlive(true, nil, true)
    end
    if target1 == player and #player:getCardIds("e") > 0 and
      room:askForSkillInvoke(player, self.name, nil, "#rfenghou__yundao1-invoke::"..target1.id) then
      local n = math.min(2, #player:getCardIds("e"))
      local cards = room:askForCardsChosen(player, player, n, n, "e", self.name, "#rfenghou__yundao-prey::"..player.id)
      room:addPlayerMark(player, "rfenghou__yundao1", 1)
      room:moveCardTo(cards, Card.PlayerHand, player, fk.ReasonPrey, self.name, nil, true, player.id)
    elseif target1 ~= player and not target1:isNude() and
      room:askForSkillInvoke(player, self.name, nil, "#rfenghou__yundao1-invoke::"..target1.id) then
      room:doIndicate(player.id, {target1.id})
      local n = math.min(2, #target1:getCardIds("he"))
      local cards = room:askForCardsChosen(player, target1, n, n, "he", self.name, "#rfenghou__yundao-prey::"..target1.id)
      room:addPlayerMark(player, "rfenghou__yundao1", 1)
      room:moveCardTo(cards, Card.PlayerHand, player, fk.ReasonPrey, self.name, nil, false, player.id)
    end
    if player.dead or target2.dead then return end
    if room:askForSkillInvoke(player, self.name, nil, "#rfenghou__yundao2-invoke::"..target2.id) then
      room:doIndicate(player.id, {target2.id})
      room:addPlayerMark(player, "rfenghou__yundao2")
      target2:drawCards(2, self.name)
    end
  end,
}
local pingtu = fk.CreateActiveSkill{
  name = "rfenghou__pingtu",
  prompt = function (self)
    if self.interaction.data == "slash" then
      local n = Self:getMark("rfenghou__yundao1") + 1
      return "#rfenghou__pingtu1::"..Self:getLastAlive(true, n).id..":"..n
    else
      local n = Self:getMark("rfenghou__yundao2") + 1
      return "#rfenghou__pingtu2::"..Self:getNextAlive(true, n).id..":"..n
    end
  end,
  min_card_num = 1,
  max_card_num = 999,
  target_num = 1,
  interaction = function()
    return U.CardNameBox {choices = {"slash", "peach"}}
  end,
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0
  end,
  card_filter = function (self, to_select, selected)
    if self.interaction.data == "slash" then
      return #selected < Self:getMark("rfenghou__yundao1") + 1
    else
      return #selected < Self:getMark("rfenghou__yundao2") + 1
    end
  end,
  target_filter = function(self, to_select, selected, selected_cards)
    if #selected == 0 then
      local target = Fk:currentRoom():getPlayerById(to_select)
      if self.interaction.data == "slash" then
        if #selected_cards == Self:getMark("rfenghou__yundao1") + 1 then
          local card = Fk:cloneCard("slash")
          card:addSubcards(selected_cards)
          card.skillName = self.name
          return target == Self:getLastAlive(true, #selected_cards) and not Self:isProhibited(target, card) and to_select ~= Self.id
        end
      else
        if #selected_cards == Self:getMark("rfenghou__yundao2") + 1 then
          local card = Fk:cloneCard("peach")
          card:addSubcards(selected_cards)
          card.skillName = self.name
          return target == Self:getNextAlive(true, #selected_cards) and not Self:isProhibited(target, card) and target:isWounded()
        end
      end
    end
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local target = room:getPlayerById(effect.tos[1])
    room:useVirtualCard(self.interaction.data, effect.cards, player, target, self.name, true)
  end
}
tuobagui:addSkill(yundao)
tuobagui:addSkill(pingtu)
Fk:loadTranslationTable{
  ["rfenghou__tuobagui"] = "拓跋珪",
  ["designer:rfenghou__tuobagui"] = "慰酒",
  ["illustrator:rfenghou__tuobagui"] = "珊瑚虫",
  ["#rfenghou__tuobagui"] = "威朔登国",

  ["rfenghou__yundao"] = "运道",
  [":rfenghou__yundao"] = "轮次开始时，你可以令『上家』和『下家』交换座次；你可以获得『上家』的两张牌，于“上家”后添加“的上家”；"..
  "你可以令『下家』摸两张牌，于“下家”后添加“的下家”。",
  ["rfenghou__pingtu"] = "平途",
  [":rfenghou__pingtu"] = "出牌阶段限一次，你可以将X张牌当【杀】对『上家』或当【桃】对『下家』使用（X为修改对应项的次数+1）。",
  ["#rfenghou__yundao-invoke"] = "运道：是否令 %src 和 %dest 交换座次？",
  ["#rfenghou__yundao1-invoke"] = "运道：是否获得 %dest 两张牌，并修改『上家』？",
  ["#rfenghou__yundao2-invoke"] = "运道：是否令 %dest 摸两张牌，并修改『下家』？",
  ["#rfenghou__yundao-prey"] = "运道：获得 %dest 两张牌",
  ["#rfenghou__pingtu1"] = "平途：你可以将%arg张牌当【杀】对 %dest 使用",
  ["#rfenghou__pingtu2"] = "平途：你可以将%arg张牌当【桃】对 %dest 使用",
}

local xumi = General:new(extension, "rfenghou__xumi", "jin", 3)
xumi.hidden = true
local rulv = fk.CreateTriggerSkill {
  name = "rfenghou__rulv",
  anim_type = "control",
  events = {fk.AskForRetrial},
  can_trigger = function(self, event, target, player, data)
    return player:hasSkill(self) and data.card.suit ~= Card.Spade and
      player:usedSkillTimes(self.name, Player.HistoryTurn) < player:getMark(self.name)
  end,
  on_cost = function (self, event, target, player, data)
    return player.room:askForSkillInvoke(player, self.name, nil, "#rfenghou__rulv-invoke::"..target.id..":"..data.reason)
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    local new_card = Fk:cloneCard(data.card.name, Card.Spade, data.card.number)
    new_card.skillName = self.name
    new_card.id = data.card.id
    data.card = new_card
    room:sendLog{
      type = "#ChangedJudge",
      from = player.id,
      to = { data.who.id },
      arg2 = new_card:toLogString(),
      arg = self.name,
    }
  end,

  refresh_events = {fk.Damaged, fk.EventAcquireSkill},
  can_refresh = function (self, event, target, player, data)
    if target == player then
      if event == fk.Damaged then
        return data.damageType == fk.ThunderDamage and player:getMark(self.name) < 3
      elseif event == fk.EventAcquireSkill then
        return data == self
      end
    end
  end,
  on_refresh = function (self, event, target, player, data)
    local room = player.room
    if event == fk.Damaged then
      room:addPlayerMark(player, self.name, 1)
    elseif event == fk.EventAcquireSkill then
      local n = math.min(3,
      #room.logic:getActualDamageEvents(3, function (e)
        local damage = e.data[1]
        return damage.to == player and damage.damageType == fk.ThunderDamage
      end, Player.HistoryGame))
      room:setPlayerMark(player, self.name, n)
    end
  end,
}
local ziyang = fk.CreateTriggerSkill{
  name = "rfenghou__ziyang",
  mute = true,
  frequency = Skill.Compulsory,
  events = {fk.DamageInflicted, fk.CardUseFinished, fk.FinishJudge},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      if event == fk.DamageInflicted then
        return target == player and data.damageType == fk.ThunderDamage
      elseif event == fk.CardUseFinished then
        return target == player and data.card.suit == Card.Spade
      elseif event == fk.FinishJudge then
        return data.card.suit == Card.Spade and player.room:getCardArea(data.card) == Card.Processing
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(self.name)
    if event == fk.DamageInflicted then
      room:notifySkillInvoked(player, self.name, "defensive")
      data.damage = data.damage - 1
      data.damage = math.min(data.damage, 1)
      if data.damage == 0 then
        return true
      end
    elseif event == fk.CardUseFinished then
      room:notifySkillInvoked(player, self.name, "offensive")
      room.tag[self.name] = room.tag[self.name] or {}
      room.tag[self.name][player.id] = room.tag[self.name][player.id] or 0
      local to = room:askForChoosePlayers(player, table.map(room.alive_players, Util.IdMapper), 1, 1,
        "#rfenghou__ziyang:::"..room.tag[self.name][player.id], self.name, false)
      to = room:getPlayerById(to[1])
      for _, p in ipairs({player, to}) do
        if not p.dead then
          local judge = {
            who = p,
            reason = "floating_thunder",
            pattern = ".|.|spade",
          }
          room:judge(judge)
          if judge.card.suit == Card.Spade then
            room.tag[self.name][player.id] = room.tag[self.name][player.id] + 1
            room:damage{
              to = p,
              damage = room.tag[self.name][player.id],
              damageType = fk.ThunderDamage,
              skillName = self.name,
            }
          end
        end
      end
    elseif event == fk.FinishJudge then
      room:notifySkillInvoked(player, self.name, "drawcard")
      room:moveCardTo(data.card, Card.PlayerHand, player, fk.ReasonJustMove, self.name, nil, true, player.id)
    end
  end,
}
xumi:addSkill(rulv)
xumi:addSkill(ziyang)
Fk:loadTranslationTable{
  ["rfenghou__xumi"] = "许谧",
  ["#rfenghou__xumi"] = "上清真人",
  ["illustrator:rfenghou__xumi"] = "乱世逐鹿",
  ["designer:rfenghou__xumi"] = "黄泉",

  ["rfenghou__rulv"] = "如律",
  [":rfenghou__rulv"] = "每回合限X次，一名角色的判定结果生效前，你可以将判定结果改为♠（X为你受到雷电伤害次数，至多为3）。",
  ["rfenghou__ziyang"] = "紫阳",
  [":rfenghou__ziyang"] = "锁定技，你受到的雷电伤害-1且至多为1；当你使用♠牌后，你需指定一名角色，与其进行"..
  "<a href='rfenghou__floating_thunder'>【浮雷】</a>判定；♠判定牌生效后，你获得之。",
  ["rfenghou__floating_thunder"] = "进行判定，若判定结果为♠，则受到X点雷电伤害（X为累积的♠判定次数）",
  ["#rfenghou__rulv-invoke"] = "如律：是否将 %dest 的“%arg”判定结果改为♠？",
  ["#rfenghou__ziyang"] = "紫阳：选择一名角色，与其进行【浮雷】判定（已累积%arg次！）",
}

local miheng = General:new(extension, "rfamehall__miheng", "qun", 3)
miheng.hidden = true
local huaici = fk.CreateTriggerSkill{
  name = "rfamehall__huaici",
  mute = true,
  frequency = Skill.Compulsory,
  derived_piles = "rfamehall__miheng_feng",
  events = {fk.RoundStart, fk.RoundEnd},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) then
      if event == fk.RoundStart then
        return true
      elseif event == fk.RoundEnd then
        return #player.room.logic:getEventsOfScope(GameEvent.Turn, 11, function (e)
          return e.data[1] == player
        end, Player.HistoryRound) > #player.room.alive_players
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    local room = player.room
    player:broadcastSkillInvoke(self.name)
    if event == fk.RoundStart then
      room:notifySkillInvoked(player, self.name, "special")
      player:addToPile("rfamehall__miheng_feng", room:getNCards(#room.alive_players), true, self.name, player.id)
      if player.dead or #player:getPile("rfamehall__miheng_feng") == 0 then return end
      if player:getMark(self.name) == 0 then
        room:setPlayerMark(player, self.name, U.getUniversalCards(room, "bt"))
      end
      local names = {}
      while true do
        local cards = table.filter(player:getMark(self.name), function (id)
          local card = Fk:getCardById(id)
          return table.find(player:getPile("rfamehall__miheng_feng"), function (id2)
            return card.name == Fk:getCardById(id2).name
          end) and not table.contains(names, card.trueName)
        end)
        if #cards > 0 then
          local use = U.askForUseRealCard(room, player, cards, nil, self.name,
            "#rfamehall__huaici-use", {expand_pile = cards, bypass_times = true}, true, true)
          if use then
            local card = Fk:cloneCard(use.card.name)
            card.skillName = self.name
            table.insert(names, card.trueName)
            room:useCard{
              card = card,
              from = player.id,
              tos = use.tos,
              extraUse = true,
            }
          else
            return
          end
        else
          return
        end
      end
    elseif event == fk.RoundEnd then
      room:notifySkillInvoked(player, self.name, "negative")
      room:loseHp(player, player.hp, self.name)
    end
  end,

  refresh_events = {fk.GameStart, fk.EventAcquireSkill, fk.EventLoseSkill, fk.Deathed, fk.StartPlayCard},
  can_refresh = function(self, event, target, player, data)
    if event == fk.GameStart then
      return player:hasSkill(self, true)
    elseif event == fk.EventAcquireSkill or event == fk.EventLoseSkill then
      return target == player and data == self and
        not table.find(player.room:getOtherPlayers(player), function(p)
          return p:hasSkill(self, true)
        end)
    elseif event == fk.EventLoseSkill or event == fk.Deathed then
      return target == player and player:hasSkill(self, true, true) and
        not table.find(player.room:getOtherPlayers(player), function(p)
          return p:hasSkill(self, true)
        end)
    elseif event == fk.StartPlayCard then
      return target == player and table.find(player.room:getOtherPlayers(player), function (p)
        return p:hasSkill(self) and #p:getPile("rfamehall__miheng_feng") > 0
      end)
    end
  end,
  on_refresh = function(self, event, target, player, data)
    local room = player.room
    if event == fk.GameStart or event == fk.EventAcquireSkill then
      for _, p in ipairs(room:getOtherPlayers(player)) do
        room:handleAddLoseSkills(p, "rfamehall__huaici&", nil, false, true)
      end
    elseif event == fk.EventLoseSkill or event == fk.Deathed then
      for _, p in ipairs(room:getOtherPlayers(player, true, true)) do
        room:handleAddLoseSkills(p, "-rfamehall__huaici&", nil, false, true)
      end
    elseif event == fk.StartPlayCard then
      local mark = {}
      for _, p in ipairs(room:getOtherPlayers(player)) do
        if p:hasSkill(self) then
          table.insertTable(mark, p:getPile("rfamehall__miheng_feng"))
        end
      end
      room:setPlayerMark(player, "rfamehall__miheng_record", mark)
    end
  end,
}
local huaici_active = fk.CreateActiveSkill{
  name = "rfamehall__huaici&",
  anim_type = "support",
  card_num = 1,
  target_num = 0,
  prompt = "#rfamehall__huaici&",
  expand_pile = function (self)
    return Self:getTableMark("rfamehall__miheng_record")
  end,
  can_use = function(self, player)
    return player:usedSkillTimes(self.name, Player.HistoryPhase) == 0 and
      #player:getTableMark("rfamehall__miheng_record") > 0
  end,
  card_filter = function (self, to_select, selected)
    return #selected == 0 and table.contains(Self:getTableMark("rfamehall__miheng_record"), to_select)
  end,
  on_use = function(self, room, effect)
    local player = room:getPlayerById(effect.from)
    local target = table.find(room:getOtherPlayers(player), function(p)
      return table.contains(p:getPile("rfamehall__miheng_feng"), effect.cards[1])
    end)
    if target == nil then return end
    room:moveCardTo(effect.cards, Card.DiscardPile, nil, fk.ReasonPutIntoDiscardPile, "rfamehall__huaici", nil, true, player.id)
    if target.dead then return end
    local card = Fk:cloneCard(Fk:getCardById(effect.cards[1]).name)
    if (card.type == Card.TypeBasic or card:isCommonTrick()) and
      card.skill:modTargetFilter(target.id, {}, player, card, false) then
      room:useVirtualCard(card.name, nil, player, target, self.name, true)
    else
      room:doIndicate(player.id, {target.id})
    end
  end,
}
Fk:addSkill(huaici_active)
local jianling = fk.CreateTriggerSkill{
  name = "rfamehall__jianling",
  switch_skill_name = "rfamehall__jianling",
  anim_type = "switch",
  frequency = Skill.Compulsory,
  events = {fk.TurnEnd},
  can_trigger = function(self, event, target, player, data)
    if player:hasSkill(self) and target ~= player then
      local card = nil
      player.room.logic:getEventsByRule(GameEvent.UseCard, 1, function (e)
        local use = e.data[1]
        if use.from == player.id or (use.tos and table.contains(TargetGroup:getRealTargets(use.tos), player.id)) then
          card = use.card
          return true
        end
      end, player.room.logic:getCurrentEvent().id)
      if card == nil then return end
      if player:getSwitchSkillState(self.name, false) == fk.SwitchYang then
        return card.color == Card.Red and card.type == Card.TypeBasic
      else
        return card.color == Card.Black and card.type == Card.TypeTrick
      end
    end
  end,
  on_use = function(self, event, target, player, data)
    player:gainAnExtraTurn(true, self.name)
  end,
}
miheng:addSkill(huaici)
miheng:addSkill(jianling)
Fk:loadTranslationTable{
  ["rfamehall__miheng"] = "祢衡",
  ["#rfamehall__miheng"] = "顺笼俯仰",
  ["illustrator:rfamehall__miheng"] = "鬼画府",
  ["designer:rfamehall__miheng"] = "玄蝶既白",

  ["rfamehall__huaici"] = "怀刺",
  [":rfamehall__huaici"] = "锁定技，每轮开始时，你将牌堆顶X张牌置于武将牌上（称为“讽”），然后视为使用任意张牌名各不相同的“讽”"..
  "（需为基本牌或普通锦囊牌）。<br>其他角色出牌阶段限一次，其可以将一张“讽”置入弃牌堆，（若为基本牌或普通锦囊牌）视为对你使用一张同名牌。<br>"..
  "每轮结束时，若你此轮执行过的回合数大于X，你失去所有体力。（X为场上角色数）",
  ["rfamehall__huaici&"] = "怀刺",
  [":rfamehall__huaici&"] = "出牌阶段限一次，你可以将祢衡的一张“讽”置入弃牌堆，若为基本牌或普通锦囊牌，视为对其使用一张同名牌。",
  ["rfamehall__jianling"] = "翦翎",
  [":rfamehall__jianling"] = "转换技，锁定技，其他角色的回合结束后，若你此回合使用或被使用过的最后一张牌为：阳：红色基本牌；阴：黑色锦囊牌，"..
  "你执行一个额外的回合。",
  ["rfamehall__miheng_feng"] = "讽",
  ["#rfamehall__huaici-use"] = "怀刺：你可以视为使用任意张牌名不同的“讽”",
  ["#rfamehall__huaici&"] = "怀刺：你可以将祢衡的一张“讽”置入弃牌堆，若为基本牌或普通锦囊牌，视为对其使用一张同名牌",
}


return extension
